#include "SDLWindow.h"
#include <Log/Log.h>
#include <Event/WindowEvent.h>
#include <Event/MouseEvent.h>
#include <ImGui/imgui_impl_sdl.h>

namespace Engine2D
{


    SDLWindow::SDLWindow(WindowArgs args)
        : Window(args)
    {

        if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
        {
            LOG_ERROR("{}", SDL_GetError());
            exit(-1);
        }

        m_window = SDL_CreateWindow(args.title.c_str(), args.x, args.y, args.width, args.height, SDL_WindowFlags::SDL_WINDOW_RESIZABLE);
        if (!m_window) {
            LOG_ERROR("{}", SDL_GetError());
            exit(-1);
        }
        LOG_INFO("Create Window: {}, {}, {}, {}, {}", args.title, args.x, args.y, args.width, args.height);
    }

    SDLWindow::~SDLWindow()
    {
        SDL_DestroyWindow(m_window);
        SDL_Quit();
    }

    void SDLWindow::PollEvent()
    {
        SDL_Event event;
        SDL_PollEvent(&event);
        ImGui_ImplSDL2_ProcessEvent(&event);
        if (m_eventHandler && s_eventMap.find((SDL_EventType)event.type) != s_eventMap.end()) {
            m_eventHandler(s_eventMap.at((SDL_EventType)event.type)(event));
        }
    }

    std::unordered_map<SDL_EventType, std::function<EventPtr(SDL_Event&)>> SDLWindow::s_eventMap{
        {SDL_QUIT, [](SDL_Event & event) { return std::make_shared<QuitEvent>(); }},
        {SDL_WINDOWEVENT, [](SDL_Event & event) -> EventPtr {
            switch (event.window.event)
            {
            case SDL_WindowEventID::SDL_WINDOWEVENT_RESIZED:
            case SDL_WindowEventID::SDL_WINDOWEVENT_MAXIMIZED:
            case SDL_WindowEventID::SDL_WINDOWEVENT_SIZE_CHANGED:
                return std::make_shared<ResizeEvent>(event.window.data1, event.window.data2);
            default: return std::make_shared<Event>();
            }
        }},
        {SDL_MOUSEMOTION, [](SDL_Event & event) {
            return std::make_shared<MouseMoveEvent>(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel, event.motion.state);
        }},
        {SDL_MOUSEBUTTONDOWN, [](SDL_Event & event) {
            return std::make_shared<MouseButtonEvent>(MouseButtonEvent::Prop{event.button.button, event.button.state, event.button.clicks, event.button.x, event.button.y});
        }},
        {SDL_MOUSEBUTTONUP, [](SDL_Event & event) {
            return std::make_shared<MouseButtonEvent>(MouseButtonEvent::Prop{event.button.button, event.button.state, event.button.clicks, event.button.x, event.button.y});
        }},
        {SDL_MOUSEWHEEL, [](SDL_Event& event) {
            return std::make_shared<MouseWheelEvent>(MouseWheelEvent::Prop{event.wheel.x, event.wheel.y, event.wheel.direction, event.wheel.preciseX, event.wheel.preciseY, event.wheel.mouseX, event.wheel.mouseY});
        }},
    };

} // namespace Engine2D
